﻿'***********************************************************************
' Assembly         : SOFA.Caching
' Copyright        : (c) Jebarson. All rights reserved.
' Website			: http://www.jebarson.info
'***********************************************************************
Imports System.Collections.Generic

Namespace Caching
    ''' <summary>
    ''' Base type for all the collection of items.
    ''' </summary>
    ''' <typeparam name="T"></typeparam>
    Public MustInherit Class StorageItemCollection(Of T As StorageItemEntry)
        Implements IList(Of StorageItemEntry)

#Region " Declarations "
        ''' <summary>
        ''' Member variable for storage dictionary.
        ''' </summary>
        Private storageDictionaryValue As Dictionary(Of String, StorageItemEntry)

        ''' <summary>
        ''' Member variable for index list.
        ''' </summary>
        Private indexListValue As List(Of String)

        ''' <summary>
        ''' Member variable for storage factory.
        ''' </summary>
        Private storageFactoryValue As CacheStorageFactory(Of ICacheStorageConfig)
#End Region

#Region " Constructors "
        ''' <summary>
        ''' Initializes a new instance of the <see cref="StorageItemCollection(Of T)" /> class.	
        ''' </summary>
        Protected Sub New()

            If Me.StorageFactory Is Nothing Then
                Me.storageFactoryValue = New CacheStorageFactory(Of ICacheStorageConfig)(Me.StorageConfig)
            End If

            Me.storageFactoryValue.SetStorageItem(Me)
        End Sub
#End Region

#Region " Public Properties "
        ''' <summary>
        ''' Gets or sets the storage dictionary.	
        ''' </summary>
        ''' <value>The storage dictionary.</value>
        Public Property StorageDictionary() As Dictionary(Of String, StorageItemEntry)
            Get
                Return Me.storageDictionaryValue
            End Get
            Set(ByVal value As Dictionary(Of String, StorageItemEntry))
                Me.storageDictionaryValue = value
            End Set
        End Property

        ''' <summary>
        ''' Gets or sets the index list.	
        ''' </summary>
        ''' <value>The index list.</value>
        Public Property IndexList() As List(Of String)
            Get
                Return Me.indexListValue
            End Get
            Set(ByVal value As List(Of String))
                Me.indexListValue = value
            End Set
        End Property

        ''' <summary>
        ''' Gets the name.	
        ''' </summary>
        ''' <value></value>
        Public ReadOnly Property Name() As String
            Get
                Return Me.StorageConfig.Storage.GetName(Me)
            End Get
        End Property

        ''' <summary>
        ''' Gets or sets the item.	
        ''' </summary>
        ''' <value>The item.</value>
        Public Property Item(ByVal key As String) As StorageItemEntry
            Get
                Return Me.StorageDictionary.Item(key)
            End Get
            Set(ByVal value As StorageItemEntry)
                Me.StorageDictionary.Item(key) = value
            End Set
        End Property
#End Region

#Region " Friend Properties "
        ''' <summary>
        ''' Gets the item entries.
        ''' </summary>
        ''' <value>The item entries.</value>
        Friend ReadOnly Property ItemEntries() As List(Of StorageItemEntry)
            Get
                Dim itemEntriesValue As List(Of StorageItemEntry) = New List(Of StorageItemEntry)

                For Each dictionaryItem As KeyValuePair(Of String, StorageItemEntry) In Me.StorageDictionary
                    itemEntriesValue.Add(dictionaryItem.Value)
                Next

                Return itemEntriesValue
            End Get
        End Property

        ''' <summary>
        ''' Gets the storage factory.
        ''' </summary>
        ''' <value>The storage factory.</value>
        Friend ReadOnly Property StorageFactory As CacheStorageFactory(Of ICacheStorageConfig)
            Get
                Return Me.storageFactoryValue
            End Get
        End Property
#End Region

#Region " Must Overrides "
        ''' <summary>
        ''' Loads the specified key.	
        ''' </summary>
        ''' <param name="key">The key.</param>
        ''' <returns></returns>
        Public MustOverride Function Load(ByVal key As String) As Object

        ''' <summary>
        ''' Loads all.	
        ''' </summary>
        ''' <returns></returns>
        Public MustOverride Function LoadAll() As List(Of DataRow)

        ''' <summary>
        ''' Gets the is lazy load.	
        ''' </summary>
        ''' <value></value>
        Public MustOverride ReadOnly Property IsLazyLoad() As Boolean

        ''' <summary>
        ''' Gets the storage config.
        ''' </summary>
        ''' <value>The storage config.</value>
        Public MustOverride ReadOnly Property StorageConfig() As ICacheStorageConfig
#End Region

#Region " Friend Methods "
        ''' <summary>
        ''' Creates the child instance.
        ''' </summary>
        ''' <returns>The instance of the type.</returns>
        Public Function CreateChildInstance() As T
            Return Activator.CreateInstance(Of T)()
        End Function
#End Region

#Region " IList Support "
        ''' <summary>
        ''' Adds the specified item.	
        ''' </summary>
        ''' <param name="item">The item.</param>
        Public Sub Add(ByVal item As StorageItemEntry) Implements ICollection(Of StorageItemEntry).Add

            If (item Is Nothing) Then
                Throw New InvalidOperationException("Cannot add a null object to the cache.")
            End If

            Me.StorageDictionary.Add(item.Key, item)
            Me.IndexList.Add(item.Key)
        End Sub

        ''' <summary>
        ''' Clears this instance.	
        ''' </summary>
        Public Sub Clear() Implements ICollection(Of StorageItemEntry).Clear
            Me.StorageDictionary.Clear()
            Me.IndexList.Clear()
        End Sub

        ''' <summary>
        ''' Determines whether [contains] [the specified item].
        ''' </summary>
        ''' <param name="item">The item.</param>
        ''' <returns>
        ''' <c>true</c> if [contains] [the specified item]; otherwise, <c>false</c>.
        ''' </returns>
        Public Function Contains(ByVal item As StorageItemEntry) As Boolean Implements ICollection(Of StorageItemEntry).Contains
            If (item Is Nothing) Then
                Throw New InvalidOperationException("Item cannot be null.")
            End If

            Return Me.StorageDictionary.ContainsKey(item.Key)
        End Function

        ''' <summary>
        ''' Copies to.	
        ''' </summary>
        ''' <param name="array">The array.</param>
        ''' <param name="arrayIndex">Index of the array.</param>
        Public Sub CopyTo(ByVal array() As StorageItemEntry, ByVal arrayIndex As Integer) Implements ICollection(Of StorageItemEntry).CopyTo
            Me.StorageDictionary.ToArray.CopyTo(array, arrayIndex)
        End Sub

        ''' <summary>
        ''' Gets the number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1" />.
        ''' </summary>
        ''' <value></value>
        ''' <returns>The number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1" />.</returns>
        Public ReadOnly Property Count() As Integer Implements ICollection(Of StorageItemEntry).Count
            Get
                Return Me.StorageDictionary.Count
            End Get
        End Property

        ''' <summary>
        ''' Gets a value indicating whether the <see cref="T:System.Collections.Generic.ICollection`1" /> is read-only.
        ''' </summary>
        ''' <value></value>
        ''' <returns>true if the <see cref="T:System.Collections.Generic.ICollection`1" /> is read-only; otherwise, false.</returns>
        Public ReadOnly Property IsReadOnly() As Boolean Implements ICollection(Of StorageItemEntry).IsReadOnly
            Get
                Return False
            End Get
        End Property

        ''' <summary>
        ''' Removes the specified item.
        ''' </summary>
        ''' <param name="item">The cached item.</param>
        ''' <returns>true if item is removed.</returns>
        Public Function Remove(ByVal item As StorageItemEntry) As Boolean Implements ICollection(Of StorageItemEntry).Remove
            If (item Is Nothing) Then
                Throw New InvalidOperationException("item cannot be null")
            End If

            Me.IndexList.Remove(item.Key)
            Return Me.StorageDictionary.Remove(item.Key)
        End Function

        ''' <summary>
        ''' Gets the enumerator.
        ''' </summary>
        ''' <returns>Enumerated items of the list.</returns>
        Public Function GetEnumerator() As IEnumerator(Of StorageItemEntry) Implements IEnumerable(Of StorageItemEntry).GetEnumerator
            Dim storageItemEntryList As New List(Of StorageItemEntry)

            For Each key As String In Me.StorageDictionary.Keys
                storageItemEntryList.Add(Me.StorageDictionary.Item(key))
            Next

            Return storageItemEntryList.GetEnumerator()
        End Function

        ''' <summary>
        ''' Indexes the of.	
        ''' </summary>
        ''' <param name="item">The cached item.</param>
        ''' <returns>Index of the list.</returns>
        Public Function IndexOf(ByVal item As StorageItemEntry) As Integer Implements IList(Of StorageItemEntry).IndexOf
            If (item Is Nothing) Then
                Throw New InvalidOperationException("item cannot be null.")
            End If

            Return Me.IndexList.IndexOf(item.Key)
        End Function

        ''' <summary>
        ''' Inserts the specified index.	
        ''' </summary>
        ''' <param name="index">The index.</param>
        ''' <param name="item">The item.</param>
        Public Sub Insert(ByVal index As Integer, ByVal item As StorageItemEntry) Implements IList(Of StorageItemEntry).Insert
            If (item Is Nothing) Then
                Throw New InvalidOperationException("Null cannot be added to cache.")
            End If

            Me.IndexList.Insert(index, item.Key)
            Me.Add(item)
        End Sub

        ''' <summary>
        ''' Gets or sets the element at the specified index.
        ''' </summary>
        ''' <value></value>
        ''' <returns>The element at the specified index.</returns>
        ''' <exception cref="T:System.ArgumentOutOfRangeException">
        ''' <paramref name="index" /> is not a valid index in the <see cref="T:System.Collections.Generic.IList`1" />.</exception>
        ''' <exception cref="T:System.NotSupportedException">The property is set and the <see cref="T:System.Collections.Generic.IList`1" /> is read-only.</exception>
        Public Property Item(ByVal index As Integer) As StorageItemEntry Implements IList(Of StorageItemEntry).Item
            Get
                Dim itemEntry = Me.Item(Me.IndexList(index))
                Recycler.RecycleManager.CheckExpiry(Of T)(itemEntry, Me)

                Return itemEntry
            End Get
            Set(ByVal value As StorageItemEntry)
                Me.Item(Me.IndexList(index)).Data = value
            End Set
        End Property

        ''' <summary>
        ''' Removes at.	
        ''' </summary>
        ''' <param name="index">The index.</param>
        Public Sub RemoveAt(ByVal index As Integer) Implements IList(Of StorageItemEntry).RemoveAt
            Me.StorageDictionary.Remove(Me.IndexList(index))
        End Sub

        ''' <summary>
        ''' Gets the enumerator1.	
        ''' </summary>
        ''' <returns></returns>
        Public Function GetEnumerator1() As System.Collections.IEnumerator Implements System.Collections.IEnumerable.GetEnumerator
            Return Me.GetEnumerator()
        End Function
#End Region

    End Class
End Namespace
